/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.service;

import java.util.Date;

import com.google.code.sapien.dao.CategoryDAO;
import com.google.code.sapien.dao.RoleDAO;
import com.google.code.sapien.dao.UserDAO;
import com.google.code.sapien.exception.ServiceException;
import com.google.code.sapien.model.Category;
import com.google.code.sapien.model.CategoryAcl;
import com.google.code.sapien.model.Role;
import com.google.code.sapien.model.User;
import com.google.code.sapien.security.CategoryPermissions;
import com.google.code.sapien.security.RolePermissions;
import com.google.code.sapien.util.SecurityUtils;
import com.google.inject.Inject;

/**
 * Default implementation of the {@link com.google.code.sapien.service.InstallSapienService}.
 * @author Adam
 * @version $Id$
 * 
 * Created on May 27, 2009 at 10:48:46 PM 
 */
public class InstallSapienService implements InstallService {
	/**
	 * The category data access object.
	 */
	private final CategoryDAO categoryDAO;

	/**
	 * The role data access object.
	 */
	private final RoleDAO roleDAO;

	/**
	 * The user data access object.
	 */
	private final UserDAO userDAO;

	/**
	 * Constructs an Install Sapien Service.
	 */
	@Inject
	public InstallSapienService(final UserDAO userDAO, final RoleDAO roleDAO, final CategoryDAO categoryDAO) {
		this.userDAO = userDAO;
		this.roleDAO = roleDAO;
		this.categoryDAO = categoryDAO;
	}

	/**
	 * Creates the default category.
	 */
	private Category createCategory() {
		Category category = new Category();
		category.setName("General");
		category.setDescription("General Category");
		category.setDiscussionCount(0);
		category.setMessageCount(0);
		category.setOrder(0);
		categoryDAO.add(category);
		return category;
	}

	/**
	 * Creates the default roles.
	 * @param category The default category.
	 * @param admin The administrator user.
	 */
	private void createRoles(final Category category, final User admin) {
		Role role = new Role();
		role.setName("Administrator");
		role.setDescription("Administrator Role");
		roleDAO.add(role);
		admin.getRoles().add(role);
		category.addAcl(new CategoryAcl(category, role,
				new CategoryPermissions(new int[] {CategoryPermissions.ADD_DISCUSSION_VALUE,
						CategoryPermissions.ADD_RESPONSE_VALUE, CategoryPermissions.EDIT_DISCUSSION_VALUE,
						CategoryPermissions.EDIT_RESPONSE_VALUE, CategoryPermissions.REMOVE_DISCUSSION_VALUE,
						CategoryPermissions.REMOVE_RESPONSE_VALUE, CategoryPermissions.SET_LOCK_VALUE,
						CategoryPermissions.SET_STICKY_VALUE})));
		role = new Role();
		role.setName("User");
		role.setDescription("Default User Role");
		role.setUserDefault(true);
		roleDAO.add(role);
		admin.getRoles().add(role);
		admin.getRoles().add(role);
		category.addAcl(new CategoryAcl(category, role,
				new CategoryPermissions(new int[] {CategoryPermissions.ADD_DISCUSSION_VALUE,
						CategoryPermissions.ADD_RESPONSE_VALUE})));
		role = new Role();
		role.setName("Guest");
		role.setDescription("Guest Role");
		role.setGuestDefault(true);
		roleDAO.add(role);
		category.addAcl(new CategoryAcl(category, role, new CategoryPermissions()));
	}

	/**
	 * {@inheritDoc}
	 * @see com.google.code.sapien.service.InstallService#install(com.google.code.sapien.model.User)
	 */
	public void install(final User admin) throws ServiceException {
		if (userDAO.listAll().size() > 0) {
			throw new ServiceException("An install has already been completed, not running install");
		}
		createRoles(createCategory(), admin);
		saveAdmin(admin);
	}

	/**
	 * Saves the administrator user.
	 * @param admin The administrator user.
	 */
	private void saveAdmin(final User admin) {
		final Date timestamp = new Date();
		admin.setCreated(timestamp);
		admin.setModified(timestamp);
		final String password = admin.getPassword();
		admin.setPassword(SecurityUtils.hash(password));
		admin.setActive(Boolean.TRUE);
		userDAO.add(admin);
	}
}
